// 防抖函数
export const deBounce = (fn, wait) => {
	let timer;
	return function () {
		if (timer) {
			clearTimeout(timer);
		}
		timer = setTimeout(() => {
			fn.apply(this, arguments);
		}, wait);
	};
};
// 深拷贝
export const deepClone = (obj = {}, hash = new WeakMap()) => {
	// 如果传入的是值类型/null，直接返回
	if (typeof obj !== 'object' || obj === null) return obj;

	// 处理过的值直接返回-处理循环引用
	if (hash.get(obj)) return hash.get(obj);

	let result = obj instanceof Array ? [] : {};
	hash.set(obj, result);
	for (const key in obj) {
		if (Object.hasOwnProperty.call(obj, key)) {
			result[key] = deepClone(obj[key], hash);
		}
	}
	return result;
};
/**
 * 深拷贝方法
 * @param {*} data 原始数据
 * @returns {*} 拷贝后的数据
 */
export const deepCopy = data => {
	const type = getDataType(data);
	let obj = null;
	if (type === 'array') {
		obj = [];
		for (let i = 0; i < data.length; i++) {
			obj.push(deepCopy(data[i]));
		}
	} else if (type === 'object') {
		obj = {};
		Object.keys(data).forEach(key => {
			obj[key] = deepCopy(data[key]);
		});
	} else {
		return data;
	}
	return obj;
};

/**
 * 节流器
 * @param {Function} fun 功能函数
 * @param {Number} delay 节流间隔
 * @returns {Function} 经节流器包装后生成的新函数, 其参数同 fun
 */
export const throttle = (fun, delay) => {
	let last, deferTimer;
	return (...args) => {
		const argsCopy = args;
		const now = new Date();
		let intervalTime;
		if (last) {
			intervalTime = now - last;
		} else {
			intervalTime = 0;
		}
		if (intervalTime < delay) {
			clearTimeout(deferTimer);
			deferTimer = setTimeout(() => {
				last = now;
				fun.apply(this, argsCopy);
			}, delay);
		} else {
			last = now;
			fun.apply(this, argsCopy);
		}
	};
};

/**
 * 返回js数据类型
 * @param {*} obj
 * @returns {String} js数据类型
 */
export const getDataType = obj => {
	// tostring会返回对应不同的标签的构造函数
	const { toString } = Object.prototype;
	const map = {
		'[object Boolean]': 'boolean',
		'[object Number]': 'number',
		'[object String]': 'string',
		'[object Function]': 'function',
		'[object Array]': 'array',
		'[object Date]': 'date',
		'[object RegExp]': 'regExp',
		'[object Undefined]': 'undefined',
		'[object Null]': 'null',
		'[object Object]': 'object'
	};
	if (obj instanceof Element) {
		return 'element';
	}
	return map[toString.call(obj)];
};

// 数字补零
export const addZero = (val) => {
	return val.toString().padStart(2,'0')
}
/**
 * 获取当前时间
 * @return {string}
 */
export const getTimeNow = () => {
	const D = new Date();
	const year = D.getFullYear();
	const mouth = D.getMonth() + 1;
	const day = D.getDate();
	const hour = D.getHours();
	const minute = D.getMinutes();
	const second = D.getSeconds();
	return `${year}-${addZero(mouth)}-${addZero(day)} ${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
};
/**
 * 生产随机字符串
 * @param {String} len 生成的字符串长度
 * @returns {String}
 */
export const randomString = (len = 10) => {
	const $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890',
		maxPos = $chars.length;
	let pwd = '';
	for (let i = 0; i < len; i++) {
		pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
	}
	return pwd;
};

/**
 * 格式化 日期的方法
 * @param {Date | String | Number | timestamp} date
 * @param {String} fmt  "yyyy-MM-dd hh:mm:ss.S" ==> 2006-07-02 08:09:04.423 ;   "yyyy-M-d h:m:s.S" ==> 2006-7-2 8:9:4.18
 * @returns {String}
 */
export const formatDate = (date, fmt) => {
	if (Object.prototype.toString.call(date) !== '[object Date]') {
		date = new Date(date);
	}
	const o = {
		'M+': date.getMonth() + 1, // 月份
		'd+': date.getDate(), // 日
		'h+': date.getHours(), // 小时
		'm+': date.getMinutes(), // 分
		's+': date.getSeconds(), // 秒
		'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
		S: date.getMilliseconds() // 毫秒
	};
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, `${date.getFullYear()}`.substr(4 - RegExp.$1.length));
	}
	for (const k in o) {
		if (new RegExp(`(${k})`).test(fmt)) {
			fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length));
		}
	}
	return fmt;
};

/**
 * 判断是否为空值  注意 0 为非空值
 * @param {*} value
 * @returns Boolean
 */
export const isEmpty = value => {
	if (value !== 0 && !value) {
		return true;
	}
	return Object.prototype.toString.call(value) === '[object Array]' && !value.length;
};

/**
 * 获取url？后面的字符串
 * @returns {Object}
 */
export const getUrlParams = () => {
	const url = window.location.href.split('?')[1], // 获取url中"?"符后的字串
		theRequest = {};
	if (url) {
		const strs = url.split('&');
		for (let i = 0; i < strs.length; i++) {
			theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1]);
		}
	}
	return theRequest;
};

/**
 * 获取窗口视图高度
 *
 * @returns {number}
 */
export const getClientHeight = () => {
	let clientHeight;
	const isBodyOrElementClientHeight = document.body.clientHeight && document.documentElement.clientHeight;
	if (isBodyOrElementClientHeight) {
		clientHeight =
			document.body.clientHeight < document.documentElement.clientHeight
				? document.body.clientHeight
				: document.documentElement.clientHeight;
	} else {
		clientHeight =
			document.body.clientHeight > document.documentElement.clientHeight
				? document.body.clientHeight
				: document.documentElement.clientHeight;
	}
	return clientHeight;
};

/**
 * 获取操作平台判断 mac or windows
 * @returns {{isWindows32: boolean, isMac: boolean, isWindows64: boolean, isWindows: boolean}}
 */
export const getOsInfo = () => {
	const agent = navigator.userAgent.toLowerCase();
	const isMac = /macintosh|mac os x/i.test(navigator.userAgent);

	const isWindows32 = agent.indexOf('win32') >= 0 || agent.indexOf('wow32') >= 0;
	const isWindows64 = agent.indexOf('win64') >= 0 || agent.indexOf('wow64') >= 0;

	return {
		isMac: isMac,
		isWindows32: isWindows32,
		isWindows64: isWindows64,
		isWindows: isWindows32 || isWindows64
	};
};
/**
 * @description 下载文件
 * @param obj {file} 文件流
 */
export function downloadFile({ file, fileName }) {
	const url = URL.createObjectURL(new Blob([file], { type: 'application/zip' }));
	const a = document.createElement('a');
	a.style.display = 'none';
	a.href = url;
	a.download = fileName;
	document.body.appendChild(a);
	a.click();
	URL.revokeObjectURL(url);
	document.body.removeChild(a);
}

/**
 * @description 高亮关键词
 * @param {String} str 源文本
 * @param {String} keyword 需要高亮的关键词
 * @param {String} color 高亮颜色
 * @returns {String}
 */
export function highLightWords(str, keyword, color = '#246FE5') {
	let res = str;
	let replaceReg = new RegExp(keyword, 'ig');
	let val = str.match(replaceReg);
	if (val) {
		let replaceString = `<span style="color: ${color}">${val[0]}</span>`;
		res = str.replace(replaceReg, replaceString);
	}
	return res;
}

/**
 * 点击弹窗外层
 * @param {Event} e event对象
 * @param {HTMLElement | HTMLDivElement} dom 监听的dom对象
 * @param {Function} cb 回调
 */
export const clickOutside = (e, dom, cb) => {
	if (!dom?.contains(e.target)) cb();
};
